<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js Context Menu Example</title>
    <style>
        body {
            margin: 0;
        }

        canvas {
            display: block;
        }

        .context-menu {
            position: absolute;
            background-color: rgb(173, 47, 47);
            border: 1px solid #ccc;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
            z-index: 1000;
        }

        .context-menu-item {
            padding: 8px 12px;
            cursor: pointer;
        }

        .context-menu-item:hover {
            background-color: #eee;
        }
    </style>
</head>

<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script>
        let scene, camera, renderer, raycaster, mouse;

        function init() {
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.rotation.set(0, 0, 0);
            camera.position.set(0, 0, 15);

            renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);

            raycaster = new THREE.Raycaster();
            mouse = new THREE.Vector2();

            const planeData = [
                {
                    imgURL: './images/souce_01.png',
                    width: 107,
                    height: 96,
                    x: -10.7,
                    y: -2.4,
                    z: 0,
                    renderOrder: 3,
                    labelObj: {
                        type: 'machine_1',
                        name: '1号机台',
                        position: [-10.7, -2.4, 0],
                    },
                },
                {
                    imgURL: './images/souce_03.png',
                    width: 111,
                    height: 102,
                    x: -1.199999,
                    y: -0.01222,
                    z: 0,
                    renderOrder: 7,
                    labelObj: {
                        type: 'machine_2',
                        name: '5号机台',
                        position: [-1.199999, -0.01222, 0],
                    },
                }
            ];

            planeData.forEach(data => createObjectWithLabel(data));

            window.addEventListener('contextmenu', onContextMenu, false);
            window.addEventListener('dblclick', onDoubleClick, false);
            window.addEventListener('click', hideContextMenu, false);

            animate();
        }

        function createObjectWithLabel(obj) {
            const textureLoader = new THREE.TextureLoader();
            const texture = textureLoader.load(obj.imgURL);
            const cur_ratio = 0.02;
            const geometry = new THREE.PlaneGeometry(obj.width * cur_ratio, obj.height * cur_ratio);

            const material = new THREE.MeshBasicMaterial({
                map: texture,
                transparent: true,
                opacity: 1,
                side: THREE.DoubleSide,
            });
            material.map.colorSpace = THREE.SRGBColorSpace;

            const plane = new THREE.Mesh(geometry, material);
            plane.material.depthWrite = false;
            plane.position.set(obj.x, obj.y, obj.z);
            plane.renderOrder = obj.renderOrder || 0;
            plane.userData = obj.labelObj;

            scene.add(plane);
        }

        function onContextMenu(event) {
            event.preventDefault();
            handleMouseEvent(event, showContextMenu);
        }

        function onDoubleClick(event) {
            event.preventDefault();
            handleMouseEvent(event, showContextMenu);
        }

        function handleMouseEvent(event, callback) {
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObjects(scene.children);

            if (intersects.length > 0) {
                const intersectedObject = intersects[0].object;
                callback(event, intersectedObject.userData);
            }
        }

        function showContextMenu(event, userData) {
            hideContextMenu();

            const menu = document.createElement('div');
            menu.className = 'context-menu';
            menu.style.top = `${event.clientY}px`;
            menu.style.left = `${event.clientX}px`;

            if (userData.type) {
                const editOption = document.createElement('div');
                editOption.className = 'context-menu-item';
                editOption.innerText = 'Edit';
                editOption.onclick = function () {
                    editPlane(userData);
                };
                menu.appendChild(editOption);

                const deleteOption = document.createElement('div');
                deleteOption.className = 'context-menu-item';
                deleteOption.innerText = 'Delete';
                deleteOption.onclick = function () {
                    deletePlane(userData);
                };
                menu.appendChild(deleteOption);

                const addChildOption = document.createElement('div');
                addChildOption.className = 'context-menu-item';
                addChildOption.innerText = 'Add Child';
                addChildOption.onclick = function () {
                    addChildPlane(userData);
                };
                menu.appendChild(addChildOption);
            }

            document.body.appendChild(menu);
        }

        function hideContextMenu() {
            const menus = document.querySelectorAll('.context-menu');
            menus.forEach(menu => menu.remove());
        }

        function editPlane(userData) {
            console.log('Editing plane:', userData);
        }

        function deletePlane(userData) {
            console.log('Deleting plane:', userData);
        }

        function addChildPlane(userData) {
            console.log('Adding child to plane:', userData);
        }

        function animate() {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        }

        window.onload = init;
    </script>
</body>

</html>